Part III: Distributing MapReduce tasks
要干什么?
前面的都是串行执行MRTask, 这次我们要用多线程模拟分布式环境, 来进行分布式MR.
具体的任务是: 完善schedule.go: schedule()
:
- 从registerChan读取已注册worker, 它会返回一个包含worker的rpc地址的字符串.
- 给每一个worker分配一系列任务
- 等待所有Task完成后, 返回
- schedule()应该使用全部worker, 有一些worker可能在schedule() 执行时才启动.
- schedul()通过
Worker.DoTask()
让worker执行任务.
前置条件
因为设计到并发编程, 所以我们可能要用到:
goroutine
channel
- go的RPC库, 用来和Worker通信
sync.WaitGroup
- Go的race detector.
-
select
语句, 用来检查超时
我们还要了解如下文件:
mapreduce/common_rpc.go
mapreduce/master.go
mapreduce/worker.go
如何调度
为每个worker一次性分配若干个task
这是作者最初的思路。
为每个task分配一个worker
这是后面采用的思路,参考了这篇博客。
具体来说,就是每一个task都开启一个单独的线程,然后每次给一个worker分配一个task,每次worker完成task后, 将worker放入registerChan
,这样worker可以等待分配下一个task.
潜在问题
笔者采用了为每个task分配一个worker。但是这里有一个坑, register是同步channel, 也就是如果A做完了任务n-2, 把A放入register之后,B做完了任务n-1,此时没有任务可执行了,那么没有线程从register里面取出A, 此时也无法把B放入register。
这就是sync chan导致的死锁,有两种解决方法:1)把register <- Name
放入一个goroutine中,这个goroutine会被阻塞但当其父线程结束时也会一起结束。2)加个条件判断,最后一个任务完成后不要把Name放进去。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。